package com.example.flutter_pangle;

import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;

import com.bytedance.sdk.shortplay.api.EpisodeData;
import com.bytedance.sdk.shortplay.api.PSSDK;
import com.bytedance.sdk.shortplay.api.ShortPlay;
import com.bytedance.sdk.shortplay.api.ShortPlayFragment;
import com.google.gson.Gson;
import com.ss.ttvideoengine.Resolution;
import com.ss.ttvideoengine.TTVideoEngineInterface;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.platform.PlatformView;

public class DetailFragmentPlatformView implements PlatformView {
  private final FrameLayout container;
  private final Handler mainHandler = new Handler(Looper.getMainLooper());
  private ShortPlayFragment fragment;
  private FragmentManager fragmentManager;
  private int containerId;
  private ActivityProvider activityProvider;
  private final EventChannel eventChannel;
  private EventChannel.EventSink eventSink;
  private final MethodChannel methodChannel;

  public interface ActivityProvider { Activity getActivity(); }

  public DetailFragmentPlatformView(
          @NonNull Context context,
          int id,
          @NonNull Object args,
          @NonNull ActivityProvider activityProvider,
          @NonNull BinaryMessenger messenger
  ) {
    this.activityProvider = activityProvider;
    container = new FrameLayout(context);
    container.setLayoutParams(new FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.MATCH_PARENT,
            FrameLayout.LayoutParams.MATCH_PARENT
    ));
    containerId = View.generateViewId();
    container.setId(containerId);

    // EventChannel per view
    eventChannel = new EventChannel(messenger, "flutter_pangle/detail_fragment_events_" + id);
    eventChannel.setStreamHandler(new EventChannel.StreamHandler() {
      @Override
      public void onListen(Object arguments, EventChannel.EventSink events) {
        eventSink = events;
      }

      @Override
      public void onCancel(Object arguments) {
        eventSink = null;
      }
    });

    // MethodChannel per view
    methodChannel = new MethodChannel(messenger, "flutter_pangle/detail_fragment_methods_" + id);
    methodChannel.setMethodCallHandler((call, result) -> {
      String method = call.method;
      if ("seekToSeconds".equals(method)) {
        try {
          Object secondsObj = call.argument("seconds");
          int seconds = 0;
          if (secondsObj != null) seconds = (int) Math.max(0, Double.valueOf(String.valueOf(secondsObj)).intValue());
          final int target = seconds;
          mainHandler.post(() -> {
            try {
              if (fragment != null) {
                fragment.setCurrentPlayTimeSeconds(target);
              }
              result.success(null);
            } catch (Throwable t) {
              result.error("SEEK_ERROR", t.getMessage(), null);
            }
          });
        } catch (Throwable t) {
          result.error("SEEK_ERROR", t.getMessage(), null);
        }
      } else if ("pausePlay".equals(method)) {
        mainHandler.post(() -> {
          try {
            if (fragment != null) fragment.pausePlay();
            result.success(null);
          } catch (Throwable t) {
            result.error("PAUSE_ERROR", t.getMessage(), null);
          }
        });
      } else if ("startPlay".equals(method)) {
        mainHandler.post(() -> {
          try {
            if (fragment != null) fragment.startPlay();
            result.success(null);
          } catch (Throwable t) {
            result.error("PLAY_ERROR", t.getMessage(), null);
          }
        });
      } else if ("setVideoSpeed".equals(method)) {
        try {
          Object speedObj = call.argument("speed");
          final float speed = speedObj == null ? 1.0f : Float.parseFloat(String.valueOf(speedObj));
          mainHandler.post(() -> {
            try {
              if (fragment != null) fragment.setVideoSpeed(speed);
              result.success(null);
            } catch (Throwable t) {
              result.error("SPEED_ERROR", t.getMessage(), null);
            }
          });
        } catch (Throwable t) {
          result.error("SPEED_ERROR", t.getMessage(), null);
        }
      } else if ("startPlayIndex".equals(method)) {
        try {
          Object idxObj = call.argument("index");
          final int idx = idxObj == null ? 0 : Math.max(0, Double.valueOf(String.valueOf(idxObj)).intValue());
          mainHandler.post(() -> {
            try {
              if (fragment != null) fragment.startPlayIndex(idx);
              result.success(null);
            } catch (Throwable t) {
              result.error("START_INDEX_ERROR", t.getMessage(), null);
            }
          });
        } catch (Throwable t) {
          result.error("START_INDEX_ERROR", t.getMessage(), null);
        }
      } else {
        result.notImplemented();
      }
    });
    @SuppressWarnings("unchecked")
    Map<?, ?> params = args instanceof Map ? (Map<?, ?>) args : null;
    String shortplayJson = null;
    boolean playSingleItem;
    int initialPlayIndex = 1;
    boolean autoPlay = false;
    if (params != null) {
      Object v = params.get("shortplay_json");
      if (v != null) shortplayJson = String.valueOf(v);
      Object p = params.get("play_single_item");
      if (p instanceof Boolean) {
        playSingleItem = (Boolean) p;
      } else {
        playSingleItem = true;
      }
      Object idx = params.get("initial_play_index");
      if (idx != null) {
        try {
          initialPlayIndex = Math.max(0, Double.valueOf(String.valueOf(idx)).intValue());
        } catch (Throwable ignored) {
        }
      }
      Object autoPlayObj = params.get("auto_play");
      if (autoPlayObj instanceof Boolean) {
        autoPlay = (Boolean) autoPlayObj;
      }
    } else {
      playSingleItem = true;
    }

    Activity activity = activityProvider.getActivity();
    if (!(activity instanceof FragmentActivity)) {
      return;
    }
    fragmentManager = ((FragmentActivity) activity).getSupportFragmentManager();

    final String json = shortplayJson;
    int finalInitialPlayIndex = initialPlayIndex;
    final boolean finalAutoPlay = autoPlay;
    mainHandler.post(() -> {
      try {
        ShortPlay shortPlay = null;
        if (json != null && !json.isEmpty()) {
          Gson gsonCls = new Gson();
          shortPlay = gsonCls.fromJson(json, ShortPlay.class);
        }
        PSSDK.DetailPageConfig.Builder builder = new PSSDK.DetailPageConfig.Builder();
        builder.hideLeftTopCloseAndTitle(true,null);
        builder.displayTextVisibility(PSSDK.DetailPageConfig.TEXT_POS_BOTTOM_DESC, false);
        builder.displayTextVisibility(PSSDK.DetailPageConfig.TEXT_POS_BOTTOM_TITLE, false);
        builder.displayProgressBar(false);
        builder.playSingleItem(playSingleItem);
        builder.displayBottomExtraView(false);
        builder.setVideoDisplayMode(TTVideoEngineInterface.IMAGE_LAYOUT_ASPECT_FILL);//IMAGE_LAYOUT_ASPECT_FILL_X / IMAGE_LAYOUT_ASPECT_FILL_Y
        builder.setCoverImageScaleType(ImageView.ScaleType.FIT_XY);
        builder.startPlayIndex(finalInitialPlayIndex);
        builder.startPlayIconImage(context.getDrawable(R.drawable.play));
        fragment = PSSDK.createDetailFragment(shortPlay, builder.build(), new PSSDK.ShortPlayDetailPageListener() {
          @Override
          public void onOverScroll(int i) {
            emit("onOverScroll", new java.util.HashMap<String, Object>() {{
              put("offset", i);
            }});
          }

          @Override
          public void onProgressChange(ShortPlay shortPlay, int i, int i1, int i2) {
            java.util.HashMap<String, Object> m = new java.util.HashMap<>();
            m.put("shortPlay", safeShortPlay(shortPlay));
            m.put("position", i);
            m.put("progress", i1);
            m.put("duration", i2);
            emit("onProgressChange", m);
          }

          @Override
          public boolean onPlayFailed(PSSDK.ErrorInfo errorInfo) {
            emit("onPlayFailed", new java.util.HashMap<String, Object>() {{
              put("error", String.valueOf(errorInfo));
            }});
            return false;
          }

          @Override
          public void onShortPlayPlayed(ShortPlay shortPlay, int i, EpisodeData episodeData) {
            java.util.HashMap<String, Object> m = new java.util.HashMap<>();
            m.put("shortPlay", safeShortPlay(shortPlay));
            m.put("position", i);
            emit("onShortPlayPlayed", m);
          }

          @Override
          public void onItemSelected(int i, ItemType itemType, int i1) {
            java.util.HashMap<String, Object> m = new java.util.HashMap<>();
            m.put("position", i);
            m.put("itemType", String.valueOf(itemType));
            m.put("subType", i1);
            emit("onItemSelected", m);
          }

          @Override
          public void onVideoPlayStateChanged(ShortPlay shortPlay, int i, int i1) {
            java.util.HashMap<String, Object> m = new java.util.HashMap<>();
            m.put("shortPlay", safeShortPlay(shortPlay));
            m.put("state", i);
            m.put("extra", i1);
            emit("onVideoPlayStateChanged", m);
          }

          @Override
          public void onVideoPlayCompleted(ShortPlay shortPlay, int i) {
            java.util.HashMap<String, Object> m = new java.util.HashMap<>();
            m.put("shortPlay", safeShortPlay(shortPlay));
            m.put("position", i);
            emit("onVideoPlayCompleted", m);
          }

          @Override
          public void onEnterImmersiveMode() {
            emit("onEnterImmersiveMode", null);
          }

          @Override
          public void onExitImmersiveMode() {
            emit("onExitImmersiveMode", null);
          }

          @Override
          public boolean isNeedBlock(ShortPlay shortPlay, int i) {
            java.util.HashMap<String, Object> m = new java.util.HashMap<>();
            m.put("shortPlay", safeShortPlay(shortPlay));
            m.put("position", i);
            emit("isNeedBlock", m);
            return false;
          }

          @Override
          public void showAdIfNeed(ShortPlay shortPlay, int i, PSSDK.ShortPlayBlockResultListener shortPlayBlockResultListener) {
            java.util.HashMap<String, Object> m = new java.util.HashMap<>();
            m.put("shortPlay", safeShortPlay(shortPlay));
            m.put("position", i);
            emit("showAdIfNeed", m);
          }

          @Override
          public void onVideoInfoFetched(ShortPlay shortPlay, int i, PSSDK.VideoPlayInfo videoPlayInfo) {
            java.util.HashMap<String, Object> m = new java.util.HashMap<>();
            m.put("shortPlay", safeShortPlay(shortPlay));
            m.put("position", i);
            if (videoPlayInfo != null) {
              m.put("videoInfo", String.valueOf(videoPlayInfo));
            }
            emit("onVideoInfoFetched", m);
          }

          @Override
          public List<View> onObtainPlayerControlViews() {
            return Collections.emptyList();
          }
        });
        if (fragment != null && fragmentManager != null && !fragmentManager.isStateSaved()) {
          fragment.setResolution(Resolution.Auto);
          fragmentManager.beginTransaction()
                  .replace(containerId, fragment)
                  .commitNowAllowingStateLoss();
          // 根据 autoPlay 参数控制是否自动播放
          if (!finalAutoPlay) {
            // 延迟一小段时间确保 Fragment 已完全初始化，然后暂停播放
            if (fragment.getView() != null) {
              fragment.getView().post(new Runnable() {
                @Override
                public void run() {
                  fragment.pausePlay();
                }
              });
            }
//            mainHandler.postDelayed(() -> {
//              try {
//                if (fragment != null) {
//                  fragment.pausePlay();
//                }
//              } catch (Throwable ignored) {}
//            }, 100);
          }
        }
      } catch (Throwable e) {
        Log.e("DetailFragmentView", "创建页面失败", e);
      }
    });
  }

  @NonNull
  @Override
  public View getView() { return container; }

  @Override
  public void dispose() {
    // 清理 Fragment 和播放资源
    mainHandler.post(() -> {
      try {
        // 先停止播放，确保 MediaCodec 在 Surface 被释放前停止
        if (fragment != null) {
          try {
            fragment.pausePlay();
            // 给 MediaCodec 一些时间完成停止操作
            mainHandler.postDelayed(() -> {
              try {
                Activity activity = activityProvider != null ? activityProvider.getActivity() : null;
                if (activity instanceof FragmentActivity && fragmentManager != null && fragment != null) {
                  if (!fragmentManager.isStateSaved()) {
                    fragmentManager.beginTransaction()
                            .remove(fragment)
                            .commitNowAllowingStateLoss();
                  }
                  fragment = null;
                }
                emit("disposed", null);
                eventSink = null;
              } catch (Throwable e) {
                Log.e("DetailFragmentView", "清理页面失败", e);
              }
            }, 50);
          } catch (Throwable e) {
            Log.e("DetailFragmentView", "停止播放失败", e);
            // 即使停止失败，也继续清理
            Activity activity = activityProvider != null ? activityProvider.getActivity() : null;
            if (activity instanceof FragmentActivity && fragmentManager != null && fragment != null) {
              if (!fragmentManager.isStateSaved()) {
                fragmentManager.beginTransaction()
                        .remove(fragment)
                        .commitNowAllowingStateLoss();
              }
              fragment = null;
            }
            emit("disposed", null);
            eventSink = null;
          }
        } else {
          emit("disposed", null);
          eventSink = null;
        }
      } catch (Throwable e) {
        Log.e("DetailFragmentView", "清理页面失败", e);
      }
    });
  }

  private void emit(String event, Map<String, Object> data) {
    if (eventSink == null) return;
    java.util.HashMap<String, Object> payload = new java.util.HashMap<>();
    payload.put("event", event);
    if (data != null) payload.put("data", data);
    try { eventSink.success(payload); } catch (Throwable ignored) {}
  }

  private Map<String, Object> safeShortPlay(ShortPlay sp) {
    java.util.HashMap<String, Object> m = new java.util.HashMap<>();
    if (sp == null) return m;
    try {
      // Align keys to Dart models.dart expectations
      m.put("id", sp.id);
      if (sp.title != null) m.put("title", sp.title);
      m.put("total", sp.total);
      try {
        int state = sp.progressState;
        m.put("progress_state", state);
      } catch (Throwable ignored) {
        m.put("progress_state", 2);
      }
      if (sp.desc != null) m.put("desc", sp.desc);
      if (sp.coverImage != null) m.put("cover_image", sp.coverImage);
      try {
        if (sp.language != null) m.put("language", sp.language);
      } catch (Throwable ignored) {
        m.put("language", null);
      }
      try {
        java.util.ArrayList<ShortPlay.ShortPlayCategory> cats = sp.categories;
        if (cats != null && !cats.isEmpty()) {
          java.util.ArrayList<java.util.HashMap<String, Object>> catList = new java.util.ArrayList<>();
          for (ShortPlay.ShortPlayCategory c : cats) {
            java.util.HashMap<String, Object> cat = new java.util.HashMap<>();
            cat.put("id", c.id);
            if (c.name != null) cat.put("name", c.name);
            cat.put("count", c.count);
            catList.add(cat);
          }
          // Also keep first category for backward compatibility
          if (!catList.isEmpty()) {
            m.put("categories", catList);
          }
        }
      } catch (Throwable ignored) {
        m.put("categories", null);
      }

      try {
        java.util.ArrayList<ShortPlay.Tag> tags = sp.tags;
        if (tags != null && !tags.isEmpty()) {
          java.util.ArrayList<java.util.HashMap<String, Object>> tagList = new java.util.ArrayList<>();
          for (ShortPlay.Tag t : tags) {
            java.util.HashMap<String, Object> tag = new java.util.HashMap<>();
            tag.put("tag_id", t.id);
            try {
              if (t.name != null) tag.put("tag_name", t.name);
            } catch (Throwable ignored) {
              tag.put("tag_name", null);
            }
            tagList.add(tag);
          }
          m.put("tags", tagList);
        }
      } catch (Throwable ignored) {
        m.put("tags", null);
      }

      m.put("totalCollectCount", sp.totalCollectCount);
      m.put("isCollected", sp.isCollected);
      m.put("sType", sp.sType);

      java.util.ArrayList<java.util.HashMap<String, Object>> episodeList = new java.util.ArrayList<>();
      for (int i = 0; i < sp.episodes.size(); i++) {
        java.util.HashMap<String, Object> e = new java.util.HashMap<>();
        e.put("index",sp.episodes.get(i).index);
        e.put("vid",sp.episodes.get(i).vid);
        e.put("country",sp.episodes.get(i).country);
        e.put("expireTime",sp.episodes.get(i).expireTime);
        e.put("id",sp.episodes.get(i).id);
        e.put("totalLikeCount",sp.episodes.get(i).totalLikeCount);
        e.put("isLiked",sp.episodes.get(i).isLiked);
        e.put("playInfoListData",sp.episodes.get(i).playInfoListData);
        episodeList.add(e);
      }
      m.put("episodes",episodeList);
    } catch (Throwable ignored) {}
    return m;
  }
}


